package jmine.tec.utils.io.http;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Map;

import jmine.tec.utils.Tuple;
import jmine.tec.utils.collection.MultiMap;
import jmine.tec.utils.io.http.exception.HttpException;

/**
 * Connector para um aplicativo http
 * 
 * @author takeshi
 */
public interface Connector {

    /**
     * Conecta
     * 
     * @throws IOException e
     * @throws HttpException e
     */
    void connect() throws IOException, HttpException;

    /**
     * verifica se o connector esta conectado
     * 
     * @return boolean
     */
    boolean isConnected();

    /**
     * Faz um 'get' no path com os parametros http passados
     * 
     * @param path String
     * @param params Map
     * @return InputStream
     * @throws IOException e
     * @throws HttpException e
     */
    InputStream makeGet(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'post' no path com os parametros http passados
     * 
     * @param path String
     * @param params Map
     * @return InputStream
     * @throws IOException e
     * @throws HttpException e
     */
    InputStream makePost(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'put' no path com os parametros http passados
     * 
     * @param path String
     * @param params Map
     * @return InputStream
     * @throws IOException e
     * @throws HttpException e
     */
    InputStream makePut(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'delete' no path com os parametros http passados
     * 
     * @param path String
     * @param params Map
     * @return InputStream
     * @throws IOException e
     * @throws HttpException e
     */
    InputStream makeDelete(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'get' no path com os parametros http passados, devolvendo uma String jah decodificada com o charset
     * 
     * @param path String
     * @param params Map
     * @return {@link Reader}
     * @throws IOException e
     * @throws HttpException e
     */
    Reader makeGetStringResponse(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'post' no path com os parametros http passados, devolvendo uma String jah decodificada com o charset
     * 
     * @param path String
     * @param params Map
     * @return {@link Reader}
     * @throws IOException e
     * @throws HttpException e
     */
    Reader makePostStringResponse(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'put' no path com os parametros http passados, devolvendo uma String jah decodificada com o charset
     * 
     * @param path String
     * @param params Map
     * @return {@link Reader}
     * @throws IOException e
     * @throws HttpException e
     */
    Reader makePutStringResponse(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * Faz um 'delete' no path com os parametros http passados, devolvendo uma String jah decodificada com o charset
     * 
     * @param path String
     * @param params Map
     * @return {@link Reader}
     * @throws IOException e
     * @throws HttpException e
     */
    Reader makeDeleteStringResponse(String path, Map<String, String> params) throws IOException, HttpException;

    /**
     * 
     */
    void close();

    /**
     * Make a multipart post
     * 
     * @param path the path
     * @param files {@link Map}
     * @param params {@link Map}
     * @return {@link InputStream}
     * @throws IOException e
     * @throws HttpException e
     */
    InputStream makeMultipartPost(String path, MultiMap<String, File> files, MultiMap<String, String> params) throws IOException,
            HttpException;

    /**
     * Make a multipart post with a string response
     * 
     * @param path the path
     * @param files {@link Map} of files
     * @param params {@link Map} of params
     * @return Reader
     * @throws IOException e
     * @throws HttpException e
     */
    Reader makeMultipartPostStringResponse(String path, MultiMap<String, File> files, MultiMap<String, String> params) throws IOException,
            HttpException;

    /**
     * Faz um request, devolvendo o corpo da mensagem e os cabecalhos
     * 
     * @param path String
     * @param method {@link HttpMethod}
     * @param headerParameters os cabecalhos a serem mandados
     * @param queryParameters os parametros
     * @param requestBody o corpo do request. Pode ser <code>null</code>
     * @return {@link Tuple} de {@link InputStream} para {@link MultiMap}
     * @throws HttpException e
     * @throws IOException e
     */
    Tuple<InputStream, MultiMap<String, String>> makeRequestWithBody(String path, HttpMethod method, MultiMap<String, String> headerParameters,
            MultiMap<String, String> queryParameters, InputStream requestBody) throws HttpException, IOException;

    /**
     * Faz um request, devolvendo o corpo da mensagem e os cabecalhos.
     * 
     * @param path String
     * @param method {@link HttpMethod}
     * @param headerParameters os cabecalhos a serem mandados
     * @param queryParameters os parametros
     * @return {@link Tuple} de {@link InputStream} para {@link MultiMap}
     * @throws HttpException e
     * @throws IOException e
     */
    Tuple<InputStream, MultiMap<String, String>> makeRequest(String path, HttpMethod method, MultiMap<String, String> headerParameters,
            MultiMap<String, String> queryParameters) throws HttpException, IOException;

    /**
     * Faz um request, devolvendo o corpo da mensagem como uma string, lendo o charset do cabecalho da resposta
     * 
     * @param path String
     * @param method {@link HttpMethod}
     * @param headerParameters os cabecalhos a serem mandados
     * @param queryParameters os parametros
     * @param requestBody o corpo do request. Pode ser <code>null</code>
     * @return {@link Tuple} de {@link InputStream} para {@link MultiMap}
     * @throws HttpException e
     * @throws IOException e
     */
    Reader makeRequestStringResponse(String path, HttpMethod method, MultiMap<String, String> headerParameters,
            MultiMap<String, String> queryParameters, InputStream requestBody) throws HttpException, IOException;

    /**
     * Faz um request, devolvendo o corpo da mensagem e os cabecalhos
     * 
     * @param path String
     * @param method {@link HttpMethod}
     * @param headerParameters os cabecalhos a serem mandados
     * @param queryParameters os parametros
     * @return {@link Tuple} de {@link InputStream} para {@link MultiMap}
     * @throws HttpException e
     * @throws IOException e
     */
    Reader makeRequestStringResponse(String path, HttpMethod method, MultiMap<String, String> headerParameters,
            MultiMap<String, String> queryParameters) throws HttpException, IOException;

    /**
     * Encoda os query parameters de acordo com o mime type application/x-www-form-urlencoded
     * 
     * @param queryParameters o mapa de parametros
     * @return String
     * @throws IOException e
     */
    String encodeParameters(MultiMap<String, String> queryParameters) throws IOException;

}
